﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;
using StreetlightGames.XnaEngine;
using StreetlightGames.SpaceShooter.Patterns;
using System.Runtime.Serialization;
using System.IO;
using System.Reflection;
using StreetlightGames.SpaceShooter.WaveMetaData;
using StreetlightGames.XnaEngine.Particles;
using StreetlightGames.SpaceShooter.Enemies;

namespace StreetlightGames.SpaceShooter
{
    public class Wave : DrawableGameComponent
    {
        private double _elapsedDelay;
        private int _index;
        private WaveData _waveData;

        /// <summary>Gets or sets the Camera value</summary>
        public ICamera Camera
        {
            get { return _camera; }
            set { _camera = value; }
        }
        private ICamera _camera;

        /// <summary>Gets the IsChallengeStage value</summary>
        public bool IsChallengeStage
        {
            get { return _waveData.IsChallengeStage; }
        }

        /// <summary>Gets the Ships value</summary>
        public List<EnemyShip> Ships
        {
            get { return _ships; }
        }
        private List<EnemyShip> _ships = new List<EnemyShip>();

        /// <summary>Gets the IsStarted value</summary>
        public bool IsStarted
        {
            get { return _isStarted; }
        }
        private bool _isStarted;

        /// <summary>Gets the IsComplete value</summary>
        public bool IsComplete
        {
            get { return _isComplete; }
        }
        private bool _isComplete;

        /// <summary>Gets the IsFormationComplete value</summary>
        public bool IsFormationComplete
        {
            get { return _isFormationComplete; }
        }
        private bool _isFormationComplete;

        /// <summary>Gets the Name value</summary>
        public string Name
        {
            get { return _waveData.Name; }
        }

        /// <summary>Gets the SoundCue value</summary>
        public string SoundCue
        {
            get { return _waveData.SoundCue; }
        }

        /// <summary>Gets or sets the MainMotherShip value</summary>
        public MotherShip MainMotherShip
        {
            get { return _mainMotherShip; }
            set { _mainMotherShip = value; }
        }
        private MotherShip _mainMotherShip;

        public Wave(Game game, WaveData waveData)
            : base(game)
        {
            _waveData = waveData;
        }

        public override void Initialize()
        {
            if (Ships.Count == 0)
            {
                foreach (ShipGroup shipGroup in _waveData.Groups)
                {
                    foreach (ShipData shipData in shipGroup.Ships)
                    {
                        EnemyShip ship = null;
                        switch (shipData.ShipType)
                        {
                            case "BeeShip":
                                ship = new Enemies.BeeShip(Game);
                                break;
                            case "ButterflyShip":
                                ship = new Enemies.ButterflyShip(Game);
                                break;
                            case "MotherShip":
                                ship = new Enemies.MotherShip(Game);
                                break;
                        }
                        if (ship != null)
                        {
                            Game.Components.Add(ship);
                            ship.Camera = Camera;
                            ship.Initialize();
                            Ships.Add(ship);
                            ship.Wave = this;
                        }
                    }
                }
            }
            base.Initialize();
        }

        public void Start()
        {
            _elapsedDelay = 0;
            _index = 0;
            _isStarted = true;
            _mainMotherShip = null;
            int shipIndex = 0;
            foreach (ShipGroup shipGroup in _waveData.Groups)
            {
                for (int i = 0; i < shipGroup.Ships.Count; i++)
                {
                    ShipData shipData = shipGroup.Ships[i];
                    EnemyShip ship = Ships[shipIndex];
                    ship.IsAlive = false;
                    ship.IsStarted = false;
                    ship.StartDelay = shipGroup.StartDelay + (double)i * shipGroup.Interval;
                    ship.Target = VectorHelper.CreateVector(shipData.Target);
                    ship.Position = VectorHelper.CreateVector(shipGroup.StartPosition);
                    ship.Velocity = VectorHelper.CreateVector(shipGroup.StartVelocity);
                    ship.Pattern = shipGroup.CreatePattern();
                    shipIndex++;
                }
            }
            return;
        }

        public override void Update(GameTime gameTime)
        {
            _elapsedDelay += gameTime.ElapsedGameTime.TotalSeconds;
            if (IsStarted && _index < Ships.Count)
            {
                foreach (EnemyShip ship in Ships)
                {
                    if (!ship.IsStarted && ship.StartDelay <= _elapsedDelay)
                    {
                        ship.Start();
                        _index++;
                    }
                }
            }
            _isComplete = _index == Ships.Count;
            bool loaded = _isComplete;
            int formationCount = 0;
            foreach (EnemyShip ship in Ships)
            {
                if (ship.IsAlive || !ship.IsStarted)
                {
                    _isComplete = false;
                }
                if (loaded && (!ship.IsAlive || ship.Pattern is Hover))
                {
                    formationCount++;
                }
            }
            if (!_isFormationComplete && formationCount == Ships.Count)
            {
                _isFormationComplete = true;
            }
            base.Update(gameTime);
        }

        internal void Stop()
        {
            foreach (EnemyShip ship in Ships)
            {
                ship.IsAlive = false;
                foreach (Missile missile in ship.Missiles)
                {
                    missile.IsAlive = false;
                }
            }
        }
    }
}
